/*************************************************************************
** Copyright(c) 2016-2025  xktesla
** All rights reserved.
** Name		: AnyT.h
** Desc		: 来源于https://blog.csdn.net/weixin_30394633/article/details/96520273。
**              改名为AnyT是为了区别于C++17的std::Any
** Author	: xktesla@2021-2-2 copy from https://blog.csdn.net/weixin_30394633/article/details/96520273
*************************************************************************/

#ifndef _74B4B1AD_0633_4D42_A664_4761888EC8E6
#define _74B4B1AD_0633_4D42_A664_4761888EC8E6

#include "depends/incfile.h"


namespace x2lib
{
    class AnyT
    {
    private:

        //非模板擦除类型
        struct Base
        {
            virtual std::unique_ptr<Base> clone() const = 0;
        };

        template<typename T>
        struct Derived : public Base
        {
            template<typename...Args>
            Derived(Args&&...args) : m_value(std::forward<Args>(args)...)
            {
            }
            std::unique_ptr<Base> clone() const
            {
                return std::unique_ptr<Base>(new Derived(m_value));
            }

            T m_value;
        };

        //拷贝使用
        std::unique_ptr<Base> clone() const
        {
            if (m_ptr)
            {
                return m_ptr->clone();
            }
            return nullptr;
        }

    public:
        //默认构造函数
        AnyT() : m_tpIndex(std::type_index(typeid(void))) {}
        AnyT(const AnyT& other) : m_ptr(other.clone()), m_tpIndex(other.m_tpIndex) {}
        AnyT(AnyT&& other) : m_ptr(std::move(other.m_ptr)), m_tpIndex(std::move(other.m_tpIndex)) {}

        //通用的右值构造
        template<typename T, class = typename std::enable_if<!std::is_same<typename std::decay<T>::type, AnyT>::value, T>::type>
        AnyT(T&& t)
#ifdef __X2LIB_WIN32__
            : m_ptr(new Derived<std::decay<T>::type>(std::forward<T>(t)))
#else
            : m_ptr(new Derived<T>(std::forward<T>(t)))
#endif
            , m_tpIndex(typeid(std::decay<T>::type)) {}

        //判断是否为空
        bool isNull()
        {
            return !bool(m_ptr);
        }

		//template<typename T, class = typename std::enable_if<!std::is_same<typename std::decay<T>::type, AnyT>::value, T>::type>
		//void build()
		//{
		//	m_ptr = new Derived<std::decay<T>::type>(std::forward<T>());
		//	m_tpIndex = typeid(std::decay<T>::type);
		//}

		void empty()
		{
			m_ptr = nullptr;
			m_tpIndex = std::type_index(typeid(void));
		}

        //是否可以类型转换
        template<class T>
        bool is() const
        {
            return m_tpIndex == std::type_index(typeid(T));
        }

        //类型转换
        template<class T>
        T& cast() const
        {
            if (!is<T>())
            {
                throw std::bad_cast();
            }
            auto ptr = dynamic_cast<Derived<T>*>(m_ptr.get());
            return ptr->m_value;
        }

        AnyT& operator=(const AnyT& other)
        {
            if (m_ptr == other.m_ptr)
            {
                return *this;
            }
            m_ptr = other.clone();
            m_tpIndex = other.m_tpIndex;
            return *this;
        }

	private:

        std::unique_ptr<Base> m_ptr;      //具体数据
        std::type_index m_tpIndex;  //数据类型
    };


	//  class AnyTSet
	//  {
	//  public:
	//      AnyTSet() {}
		  //AnyTSet(const AnyT& anyt) { Put(anyt); }

	//      //inline T* Get(uint16_t id)
	//      //{
	//      //    std::unordered_map<uint16_t, AnyT>::iterator it = m_atSet.find(id);
	//      //    if (it != m_atSet.end())
	//      //    {
	//      //        return &it->second.cast<T>();
	//      //    }
	//      //    return nullptr;
	//      //}
		  //template<class T> inline T& Get()
		  //{
		  //	std::unordered_map<uint16_t, AnyT>::iterator it = m_atSet.find(T::ItemId);
		  //	if (it != m_atSet.end())
		  //	{
		  //		return it->second.cast<T>();
		  //	}
		  //	return T;
		  //}

	//      //inline void Put(uint16_t id, AnyT& it)
	//      //{
	//      //    m_atSet.insert(std::make_pair(id, it));
	//      //}
		  //template<class T> inline AnyTSet& Put(T& it)
		  //{
		  //    m_atSet.insert[T::ItemId] = it;
		  //	return *this;
		  //}

	//      inline void Clear() { m_atSet.clear(); }
	//      inline uint32_t Size() { return m_atSet.size(); }

	//  private:
	//      std::unordered_map<uint16_t, AnyT> m_atSet;
	//  };


}

#endif
